package common;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.File;
import java.net.ServerSocket;
import java.util.Calendar;
import java.util.Map;
import java.util.TreeMap;

import objects.GameServer;
import objects.InterServerThread;
import objects.RealmServerThread;


public class RealmServer implements Runnable
{
	private static Thread _interThread,_realmThread;
	private static boolean _running = false;
	private static Map<Byte,GameServer> _gameServers = new TreeMap<Byte,GameServer>();
	
	/**
	 * @param args Name of the Config File
	 */
	public static void main(String[] args)
	{	
		writeLine("Ancestra 1.0 Realm Server");
		writeLine("By Poisskai for Dofus 1.29.1");
		writeLine("Thanks to Mellancholia & Diabu");
		writeLine("==============================================================");
		writeLine("&Loading configuration : ");
		
		String file = "realm.conf";
		if(args.length>0)
		{
			file = args[0];
		}
		RealmConf.loadConfigFile(file);
		
		if(RealmConf._debug)writeLine("Debug mode on !");
		writeLine("Database Connexion Test...");
		//Initialize the SQLManager with 10 threads
		new SQLMgr((byte)10);
		long l = SQLMgr.onInitTest();
		//If test fails
		if(l == -1)
		{
			writeLine("Error while testing the Database Connexion, please verify your configuration");
			return;
		}
		writeLine("Test suceed : There are "+l+" accounts in the database");
		writeLine("&Launching inter-server socket on port "+RealmConf._interPort+"... ");
		_interThread = new Thread(new RealmServer()); // Create an interServer when a GameServer connect to it
		_interThread.setDaemon(false);
		_interThread.start();
		
		try{Thread.sleep(500);}catch(Exception E){};
		
		writeLine("&Launching realm-server socket on port "+RealmConf._realmPort+"... ");
		_realmThread = new Thread(new RealmServerThread()); // Create the realmServer for clients
		_realmThread.setDaemon(false);
		_realmThread.start();
	}
	
	/**
	 * getter for running field
	 * @return running value
	 */
	public static boolean isRunning()
	{
		return _running;
	}
	
	/**
	 * Run method for Runnable Object
	 */
	public void run()
	{
		try {
			ServerSocket ss = new ServerSocket(RealmConf._interPort); // When GameServer connect to it
			_running = true;
			writeLine("Ok!");
			while(_running)//block on _SS.accept()
			{
				try
				{
					new InterServerThread(ss.accept()); // Create the GS InterServer
				}catch(Exception e)
				{
					writeLine("Error: "+e.getMessage());
					e.printStackTrace();
					writeLine("Server is now exiting...");
					System.exit(1);
				}
			}
		} catch (IOException e)
		{
			writeLine("Error: Inter-server socket cannot be open");
			writeLine("Maybe the port is not available...");
			writeLine("Server is now exiting...");
			System.exit(1);
			return;
		}
	}
	
	/**
	 * Write a line into log File & Console
	 * @param line : The line to write on Console & Logs
	 */
	public static void writeLine(String line)
	{
		if(line.charAt(0) == '&')
		{
			line = line.substring(1);
			System.out.print(line);
			
		}else System.out.println(line);
		if(!RealmConf._log)return;
		String time = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)+":"+Calendar.getInstance().get(+Calendar.MINUTE)+":"+Calendar.getInstance().get(Calendar.SECOND);
		String date = Calendar.getInstance().get(Calendar.DAY_OF_MONTH)+"_"+Calendar.getInstance().get(Calendar.MONTH)+"_"+Calendar.getInstance().get(Calendar.YEAR);
		BufferedWriter log;
		try {
			File f = new File("./Realm_Logs/");
			//If Directory does not exist, create the Directory
			if(!f.exists())f.mkdir();
			log = new BufferedWriter(new FileWriter("./Realm_Logs/"+date+".txt"));
			log.write(time + " > " + line+"\r\n");
			log.flush();
			log.close();
		} catch (IOException e) {
			System.out.println("Warning: Log file cannot be opened, logs are now desactivate.");
			RealmConf._log = false;
		}
	}

	public static boolean addGameServer(byte id, GameServer gS)
	{
		synchronized(_gameServers)
		{
			//If a server is already registered with this ID and isn't offline
			if(_gameServers.get(id) != null)
				if(_gameServers.get(id).getState() != Constants.SERVER_STATE_OFFLINE)
					return false;
			_gameServers.put(id, gS);
			return true;
		}
	}

	public static Map<Byte,GameServer> getGameServers()
	{
		return _gameServers;
	}
}
